package com.eshop.modules.product.rest;

import java.lang.invoke.SerializedLambda;
import java.util.Collections;
import java.util.HashMap;

import com.eshop.modules.product.domain.StoreProductAttr;
import com.eshop.modules.template.domain.ShippingTemplates;
import com.eshop.enums.SpecTypeEnum;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import org.springframework.beans.BeanUtils;
import com.eshop.modules.product.service.dto.ProductFormatDto;
import com.eshop.modules.product.domain.StoreProductAttrValue;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.eshop.modules.product.domain.StoreProductAttrResult;
import java.util.Arrays;
import cn.hutool.core.bean.BeanUtil;
import com.eshop.modules.product.service.dto.ProductDto;
import com.eshop.modules.product.domain.StoreProduct;
import java.util.LinkedHashMap;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSON;
import org.springframework.web.bind.annotation.DeleteMapping;
import java.io.Serializable;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.cache.annotation.CacheEvict;
import com.eshop.modules.aop.ForbidSubmit;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.validation.annotation.Validated;
import com.eshop.modules.product.service.dto.StoreProductDto;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import io.swagger.annotations.ApiOperation;
import com.eshop.logging.aop.log.Log;
import java.util.List;
import org.springframework.http.HttpStatus;
import java.util.Map;
import java.util.ArrayList;
import com.eshop.enums.ShopCommonEnum;
import com.eshop.modules.category.domain.StoreCategory;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import org.springframework.http.ResponseEntity;
import org.springframework.data.domain.Pageable;
import com.eshop.modules.product.service.dto.StoreProductQueryCriteria;
import com.eshop.dozer.service.IGenerator;
import com.eshop.modules.product.service.StoreProductAttrValueService;
import com.eshop.modules.product.service.StoreProductAttrResultService;
import com.eshop.modules.product.service.StoreProductRuleService;
import com.eshop.modules.template.service.ShippingTemplatesService;
import com.eshop.modules.category.service.StoreCategoryService;
import com.eshop.modules.product.service.StoreProductService;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import io.swagger.annotations.Api;

@Api(tags = { "商城:商品管理" })
@RestController
@RequestMapping({ "api" })
public class StoreProductController
{
    private final StoreProductService storeProductService;
    private final StoreCategoryService storeCategoryService;
    private final ShippingTemplatesService shippingTemplatesService;
    private final StoreProductRuleService storeProductRuleService;
    private final StoreProductAttrResultService storeProductAttrResultService;
    private final StoreProductAttrValueService storeProductAttrValueService;
    private final IGenerator generator;
    
    public StoreProductController(final StoreProductService storeProductService, final StoreCategoryService storeCategoryService, final ShippingTemplatesService shippingTemplatesService, final StoreProductRuleService storeProductRuleService, final StoreProductAttrResultService storeProductAttrResultService, final StoreProductAttrValueService storeProductAttrValueService, final IGenerator generator) {
        this.storeProductService = storeProductService;
        this.storeCategoryService = storeCategoryService;
        this.shippingTemplatesService = shippingTemplatesService;
        this.storeProductRuleService = storeProductRuleService;
        this.storeProductAttrResultService = storeProductAttrResultService;
        this.storeProductAttrValueService = storeProductAttrValueService;
        this.generator = generator;
    }
    
    @Log("查询商品")
    @ApiOperation("查询商品")
    @GetMapping({ "/yxStoreProduct" })
    @PreAuthorize("hasAnyRole('admin','YXSTOREPRODUCT_ALL','YXSTOREPRODUCT_SELECT')")
    public ResponseEntity getYxStoreProducts(final StoreProductQueryCriteria criteria, final Pageable pageable) {
        final List<StoreCategory> storeCategories = (List<StoreCategory>)((this.storeCategoryService.lambdaQuery().eq(StoreCategory::getIsShow, ShopCommonEnum.SHOW_1.getValue())).orderByAsc(StoreCategory::getPid)).list();
        final List<Map<String, Object>> cateList = new ArrayList<Map<String, Object>>();
        final Map<String, Object> queryAll = (Map<String, Object>)this.storeProductService.queryAll(criteria, pageable);
        queryAll.put("cateList", this.makeCate(storeCategories, cateList, 0, 1));
        return new ResponseEntity(queryAll, HttpStatus.OK);
    }
    
    @ForbidSubmit
    @Log("新增/修改商品")
    @ApiOperation("新增/修改商品")
    @CacheEvict(cacheNames = { "yshop:index_data" }, allEntries = true)
    @PostMapping({ "/yxStoreProduct/addOrSave" })
    @PreAuthorize("hasAnyRole('admin','YXSTOREPRODUCT_ALL','YXSTOREPRODUCT_CREATE')")
    public ResponseEntity create(@Validated @RequestBody final StoreProductDto storeProductDto) {
        this.storeProductService.insertAndEditYxStoreProduct(storeProductDto);
        return new ResponseEntity(HttpStatus.CREATED);
    }
    
    @ForbidSubmit
    @Log("删除商品")
    @ApiOperation("删除商品")
    @CacheEvict(cacheNames = { "yshop:index_data" }, allEntries = true)
    @DeleteMapping({ "/yxStoreProduct/{id}" })
    @PreAuthorize("hasAnyRole('admin','YXSTOREPRODUCT_ALL','YXSTOREPRODUCT_DELETE')")
    public ResponseEntity delete(@PathVariable final Long id) {
        this.storeProductService.removeById((Serializable)id);
        return new ResponseEntity(HttpStatus.OK);
    }
    
    @ApiOperation("商品上架/下架")
    @CacheEvict(cacheNames = { "yshop:index_data" }, allEntries = true)
    @PostMapping({ "/yxStoreProduct/onsale/{id}" })
    public ResponseEntity onSale(@PathVariable final Long id, @RequestBody final String jsonStr) {
        final JSONObject jsonObject = JSON.parseObject(jsonStr);
        final Integer status = jsonObject.getInteger("status");
        this.storeProductService.onSale(id, status);
        return new ResponseEntity(HttpStatus.OK);
    }
    
    @ApiOperation("生成属性（添加活动产品专用）")
    @PostMapping({ "/yxStoreProduct/isFormatAttrForActivity/{id}" })
    public ResponseEntity isFormatAttrForActivity(@PathVariable final Long id, @RequestBody final String jsonStr) {
        return new ResponseEntity(this.storeProductService.getFormatAttr(id, jsonStr, true), HttpStatus.OK);
    }
    
    @ApiOperation("生成属性")
    @PostMapping({ "/yxStoreProduct/isFormatAttr/{id}" })
    public ResponseEntity isFormatAttr(@PathVariable final Long id, @RequestBody final String jsonStr) {
        return new ResponseEntity(this.storeProductService.getFormatAttr(id, jsonStr, false), HttpStatus.OK);
    }
    
    @ApiOperation("获取商品信息")
    @GetMapping({ "/yxStoreProduct/info/{id}" })
    public ResponseEntity info(@PathVariable final Long id) {
        final Map<String, Object> map = new LinkedHashMap<String, Object>(3);
        final List<ShippingTemplates> shippingTemplatesList = (List<ShippingTemplates>)this.shippingTemplatesService.list();
        map.put("tempList", shippingTemplatesList);
        final List<StoreCategory> storeCategories = ((this.storeCategoryService.lambdaQuery().eq(StoreCategory::getIsShow, ShopCommonEnum.SHOW_1.getValue())).orderByAsc(StoreCategory::getPid)).list();
        final List<Map<String, Object>> cateList = new ArrayList<Map<String, Object>>();
        map.put("cateList", this.makeCate(storeCategories, cateList, 0, 1));
        map.put("ruleList", this.storeProductRuleService.list());
        if (id == 0L) {
            return new ResponseEntity(map, HttpStatus.OK);
        }
        final StoreProduct storeProduct = (StoreProduct)this.storeProductService.getById((Serializable)id);
        final ProductDto productDto = new ProductDto();
        BeanUtil.copyProperties(storeProduct, productDto, new String[] { "sliderImage" });
        productDto.setSliderImage((List)Arrays.asList(storeProduct.getSliderImage().split(",")));
        final StoreProductAttrResult storeProductAttrResult = (StoreProductAttrResult)this.storeProductAttrResultService.getOne((Wrappers.<StoreProductAttrResult>lambdaQuery().eq(StoreProductAttrResult::getProductId, id)).last("limit 1"));
        final JSONObject result = JSON.parseObject(storeProductAttrResult.getResult());
        final List<StoreProductAttrValue> attrValues = this.storeProductAttrValueService.list(Wrappers.<StoreProductAttrValue>lambdaQuery().eq(StoreProductAttrValue::getProductId, storeProduct.getId()));
        final List<ProductFormatDto> productFormatDtos = attrValues.stream().map(i -> {
            ProductFormatDto productFormatDto = new ProductFormatDto();
            BeanUtils.copyProperties(i, productFormatDto);
            productFormatDto.setPic(i.getImage());
            return productFormatDto;
        }).collect(Collectors.toList());
        if (SpecTypeEnum.TYPE_1.getValue().equals(storeProduct.getSpecType())) {
            productDto.setAttr(new ProductFormatDto());
            productDto.setAttrs((List)productFormatDtos);
            productDto.setItems((List)result.getObject("attr", (Class)ArrayList.class));
        }
        else {
            this.productFromat(productDto, result);
        }
        map.put("productInfo", productDto);
        return new ResponseEntity(map, HttpStatus.OK);
    }
    
    private void productFromat(final ProductDto productDto, final JSONObject result) {
        final Map<String, Object> mapAttr = (Map<String, Object>) (result.getObject("value", ArrayList.class)).get(0);
        final ProductFormatDto productFormatDto = ProductFormatDto.builder().pic(mapAttr.get("pic").toString()).price(Double.valueOf(mapAttr.get("price").toString())).cost(Double.valueOf(mapAttr.get("cost").toString())).otPrice(Double.valueOf(mapAttr.get("otPrice").toString())).stock(Integer.valueOf(mapAttr.get("stock").toString())).barCode(mapAttr.get("barCode").toString()).weight(Double.valueOf(mapAttr.get("weight").toString())).volume(Double.valueOf(mapAttr.get("volume").toString())).value1(mapAttr.get("value1").toString()).integral(Integer.valueOf((mapAttr.get("integral") != null) ? Integer.valueOf(mapAttr.get("integral").toString()) : 0)).brokerage(Double.valueOf(mapAttr.get("brokerage").toString())).brokerageTwo(Double.valueOf(mapAttr.get("brokerageTwo").toString())).pinkPrice(Double.valueOf(mapAttr.get("pinkPrice").toString())).pinkStock(Integer.valueOf(mapAttr.get("pinkStock").toString())).seckillPrice(Double.valueOf(mapAttr.get("seckillPrice").toString())).seckillStock(Integer.valueOf(mapAttr.get("seckillStock").toString())).build();
        productDto.setAttr(productFormatDto);
    }
    
    private List<Map<String, Object>> makeCate(final List<StoreCategory> data, final List<Map<String, Object>> cateList, final int pid, final int level) {
        final String html = "|-----";
        String newHtml = "";
        final List<StoreCategory> storeCategories = (List<StoreCategory>)(this.storeCategoryService.lambdaQuery().eq(StoreCategory::getPid, 0)).list();
        for (int i = 0; i < data.size(); ++i) {
            final StoreCategory storeCategory = data.get(i);
            final int catePid = storeCategory.getPid();
            final Map<String, Object> map = new HashMap<String, Object>();
            if (catePid == pid) {
                newHtml = String.join("", Collections.nCopies(level, html));
                map.put("value", storeCategory.getId());
                map.put("label", newHtml + storeCategory.getCateName());
                if (storeCategory.getPid() == 0) {
                    map.put("disabled", 0);
                }
                else {
                    map.put("disabled", 1);
                }
                cateList.add(map);
                data.remove(i);
                --i;
                if (storeCategory.getPid() > 0) {
                    this.makeCate(data, cateList, storeCategory.getPid(), level);
                }
                else {
                    this.makeCate(data, cateList, storeCategory.getId(), level + 1);
                }
            }
        }
        return cateList;
    }
}
